package com.tanhua.back.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.back.Dto.PageResult;
import com.tanhua.back.entity.*;
import com.tanhua.back.mapper.UserInfoMapper;
import com.tanhua.back.mapper.UserMapper;
import com.tanhua.back.mapper.UsersMapper;
import com.tanhua.back.service.UserService;
import com.tanhua.back.vo.CommentVo;
import com.tanhua.back.vo.UserInfoVo;
import com.tanhua.back.vo.UserPageVo;
import com.tanhua.back.vo.VideoBackVo;
import com.tanhua.model.domain.mongodb.Movement;
import com.tanhua.model.vo.VideoVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author maorf
 * @version 1.0
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserInfo> implements UserService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public PageResult list(Integer page, Integer pagesize, Long id, String nickname, String city) {
        Page<UserInfo> page1 = new Page<>(page, pagesize);
        LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(!ObjectUtils.isEmpty(id), UserInfo::getId, id);
        wrapper.like(!ObjectUtils.isEmpty(nickname), UserInfo::getNickname, nickname);
        wrapper.like(!ObjectUtils.isEmpty(city), UserInfo::getCity, city);
        page(page1, wrapper);
        List<UserInfo> records = page1.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return new PageResult(page, pagesize, Math.toIntExact(page1.getTotal()), null);
        }
        List<UserPageVo> list = new ArrayList<>();
        for (UserInfo record : records) {
            UserPageVo userInfoVo = new UserPageVo();
            userInfoVo.setId(Math.toIntExact(record.getId()));
            userInfoVo.setNickname(record.getNickname());
            User user = usersMapper.selectById(record.getId());
            userInfoVo.setMobile(user.getMobile());
            userInfoVo.setSex(record.getGender().equals("man") ? "男" : "女");
            userInfoVo.setAge(record.getAge());
            userInfoVo.setIncome(Integer.valueOf(record.getIncome()) * 100);
            userInfoVo.setOccupation(record.getProfession());
            userInfoVo.setUserStatus(findUserStatus(record.getId()));
            userInfoVo.setCreated(record.getCreated().getTime());
            userInfoVo.setCity(record.getCity());
            userInfoVo.setLastActiveTime(findLastActiveTime(record.getId()));
            userInfoVo.setLogo(record.getAvatar());
            list.add(userInfoVo);
        }
        return new PageResult(page, pagesize, (int) page1.getTotal(), list);

    }

    @Override
    public UserInfoVo findById(Long userID) {
        UserInfo userInfo = this.getOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getId, userID));
        UserInfoVo userInfoVo = new UserInfoVo();
        userInfoVo.setId(Math.toIntExact(userInfo.getId()));
        userInfoVo.setNickname(userInfo.getNickname());
        User user = usersMapper.selectById(userInfo.getId());
        userInfoVo.setMobile(user.getMobile());
        userInfoVo.setSex(userInfo.getGender().equals("man") ? "男" : "女");
        userInfoVo.setAge(userInfo.getAge());
        userInfoVo.setIncome(Integer.valueOf(userInfo.getIncome()) * 100);
        userInfoVo.setOccupation(userInfo.getProfession());
        userInfoVo.setUserStatus(findUserStatus(userInfo.getId()));
        userInfoVo.setCreated(userInfo.getCreated().getTime());
        userInfoVo.setCity(userInfo.getCity());
        userInfoVo.setLastActiveTime(findLastActiveTime(userInfo.getId()));
        userInfoVo.setLogo(userInfo.getAvatar());
        userInfoVo.setTags(userInfo.getTags());
        userInfoVo.setPersonalSignature("天天开心");
        userInfoVo.setCountLiked(findCountLikedById(userID));
        userInfoVo.setCountBeLiked(findCountBeLikedById(userID));
        userInfoVo.setCountMatching(findCountMatching(userID));
        userInfoVo.setLastLoginLocation(findLastLoginLocation(userID));
        return userInfoVo;


    }

    /**
     * 分页查询视频
     *
     * @param page
     * @param pagesize
     * @param sortProp
     * @param sortOrder
     * @param uid
     * @return
     */
    @Override
    public PageResult videos(Integer page, Integer pagesize, String sortProp, String sortOrder, Long uid) {
        //1.根据用户id查询用户信息
        UserInfoVo userInfoVo = this.findById(uid);
        //2.根据用户id查询videos
        Pageable pageable = PageRequest.of(page - 1, pagesize);
        Criteria c = new Criteria();
        c = Criteria.where("userId").is(uid);
        List<Video> videos = new ArrayList<>();
        //升序
        if (StringUtils.pathEquals(sortOrder, "ascending")) {
            if (StringUtils.pathEquals(sortProp, "createDate")) {
                mongoTemplate.find(Query.query(c).with(pageable).with(Sort.by(Sort.Order.asc("created"))), Video.class);
            } else {
                mongoTemplate.find(Query.query(c).with(pageable).with(Sort.by(Sort.Order.asc(sortProp))), Video.class);

            }

        } else if (StringUtils.pathEquals(sortOrder, "descending")) {
            //降序排列
            if (StringUtils.pathEquals(sortProp, "createDate")) {
                videos = mongoTemplate.find(Query.query(c).with(pageable).with(Sort.by(Sort.Order.desc("created"))), Video.class);
            } else {
                videos = mongoTemplate.find(Query.query(c).with(pageable).with(Sort.by(Sort.Order.desc(sortProp))), Video.class);

            }
        }
        videos = mongoTemplate.find(Query.query(c), Video.class);
        List<VideoBackVo> videoBackVos = new ArrayList<>();
        for (Video video : videos) {
            VideoBackVo vo = new VideoBackVo();
            BeanUtils.copyProperties(video, vo);
            vo.setNickname(userInfoVo.getNickname());
            vo.setCreateDate(video.getCreated());
            videoBackVos.add(vo);
        }
        return new PageResult(page, pagesize, videoBackVos.size(), videoBackVos);
    }

    //评论翻页
    @Override
    public PageResult comments(Integer page, Integer pagesize, String sortProp, String sortOrder, Long messageID) {
        //1.根据动态id查询评论列表
        //2.根据用户id查询comments
        Pageable pageable = PageRequest.of(page - 1, pagesize);
        Criteria c = new Criteria();
        c.where("publishId").is(messageID);
        //升序
        if (StringUtils.pathEquals(sortOrder, "ascending")) {
            if (StringUtils.pathEquals(sortProp, "createDate")) {
                mongoTemplate.find(Query.query(c).with(pageable).with(Sort.by(Sort.Order.asc("created"))), Comment.class);
            } else {
                mongoTemplate.find(Query.query(c).with(pageable).with(Sort.by(Sort.Order.asc(sortProp))), Comment.class);

            }

        } else if (StringUtils.pathEquals(sortOrder, "descending")) {
            //降序排列
            if (StringUtils.pathEquals(sortProp, "createDate")) {
                mongoTemplate.find(Query.query(c).with(pageable).with(Sort.by(Sort.Order.desc("created"))), Comment.class);
            } else {
                mongoTemplate.find(Query.query(c).with(pageable).with(Sort.by(Sort.Order.desc(sortProp))), Comment.class);

            }
        }
        List<Comment> comments = mongoTemplate.find(Query.query(c), Comment.class);
        List<CommentVo> vos = new ArrayList<>();
        for (Comment comment : comments) {
            UserInfo info = userInfoMapper.selectById(comment.getUserId());
            CommentVo vo = CommentVo.init(info, comment);
            vos.add(vo);
        }
        return new PageResult(page, pagesize, vos.size(), vos);
    }

    public Integer findCountBeLikedById(Long userId) {
        Query query = Query.query(Criteria.where("likeUserId").is(userId));
        long count = mongoTemplate.count(query, "user_like");
        return Math.toIntExact(count);
    }

    public Integer findCountLikedById(Long userId) {
        Query query = Query.query(Criteria.where("userId").is(userId));
        long count = mongoTemplate.count(query, "user_like");
        return Math.toIntExact(count);
    }

    public Integer findCountMatching(Long userId) {
        Query query = Query.query(Criteria.where("userId").is(userId));
        long count = mongoTemplate.count(query, "friend");
        return Math.toIntExact(count);
    }

    public String findUserStatus(Long userId) {
        Object freezingRange = redisTemplate.opsForHash().get("freeze_" + userId, "freezingRange");
        if (ObjectUtils.isEmpty(freezingRange)) {
            return "1";
        } else {
            return "2";
        }
    }

    public Long findLastActiveTime(Long userId) {
        Query query = Query.query(Criteria.where("userId").is(userId));
        UserLocation userLocations = mongoTemplate.findOne(query, UserLocation.class);
        if (ObjectUtils.isEmpty(userLocations)) {
            return Long.valueOf(-1);
        } else {
            return (userLocations.getLastUpdated());
        }
    }

    public String findLastLoginLocation(Long userId) {
        Query query = Query.query(Criteria.where("userId").is(userId));
        UserLocation userLocations = mongoTemplate.findOne(query, UserLocation.class);
        if (ObjectUtils.isEmpty(userLocations)) {
            return "";
        } else {
            return (userLocations.getAddress());
        }
    }
}
